﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;

using Moe.ECamel.Common.Entities;

namespace Moe.ECamel.Server.BL
{
	/// <summary>
	/// Business Logic component for Users.
	/// </summary>
	public class UserBL : ECamelBL
	{
		/// <summary>
		/// Default constructor for business logic component.
		/// </summary>
		/// <param name="dataContext">Data context to be used by this component's operations.</param>
		public UserBL(ECamelDataContext dataContext)
			: base(dataContext)
		{
		}

		public ECamelError CreateUser(User user)
		{
			// Validate:
			ECamelError validationError = ValidateUser(user);
			if (validationError != null)
				return validationError;

			// Insert:
			dataContext.Users.InsertOnSubmit(user);
			//dataContext.UserRoles.InsertAllOnSubmit(user.UserRoles);

			// Return with no error:
			return null;
		}
		public ECamelError UpdateUser(User user)
		{
			// Validate:
			ECamelError validationError = ValidateUser(user);
			if (validationError != null)
				return validationError;

			// Update:
			dataContext.Users.Attach(user, true);

			// Return with no error:
			return null;
		}

		public User GetUserById(int userId)
		{
			return (from u in dataContext.Users where u.UserId == userId select u).Single();
		}

		public User GetUserByUsername(String username)
		{
			// Configure load options:
			DataLoadOptions loadOptions = new DataLoadOptions();
			loadOptions.LoadWith<User>(u => u.UserRoles);
			ECamelDataContext adhocDC = new ECamelDataContext(dataContext.Connection);
			adhocDC.ObjectTrackingEnabled = false;
			adhocDC.LoadOptions = loadOptions;

			// Find user by username:
			return  (from u in adhocDC.Users
					 where u.Username == username
					 select u).SingleOrDefault();
		}

		public IList<Operation> GetUserOperations(int userId)
		{
			// Get all the operations which the user is authorized to perform:
			var operations = (from ro in dataContext.RoleOperations
							  join ur in dataContext.UserRoles on ro.RoleId equals ur.RoleId
							  where ur.UserId == userId
							  select ro.Operation).Distinct().ToList();

			return operations;
		}
		private ECamelError ValidateUser(User user)
		{
			// Validate user details:
			ECamelError validationError = user.Validate();
			if (validationError != null)
				return validationError;

			// Validate user name is unique:
			int others = (from u in dataContext.Users
						  where u.Username == user.Username && u.UserId != user.UserId
						  select u.UserId).Count();
			if (others > 0)
				return new ECamelError(MessageIds.UserInvalidDuplicateName);

			return null;
		}
	}
}